import VNode from "../../vdom/vnode.js";
import { getValue } from "../../util/ObjectUtil.js";

export function vforInit(vm, elm, parent, instructions) {
  // instructions为传入的v-for的指令(形如(key) in list)
  // 生成虚拟节点，虚拟节点的nodeType为0
  let virtualNode = new VNode(
    elm.nodeName,
    0,
    "",
    elm,
    [],
    parent,
    getVirtualNodeData(instructions)[2]
  ); // 0表示节点类型为0，代表虚拟节点
  virtualNode.instructions = instructions; // 把指令赋值给虚拟节点的instructions属性
  parent.elm.removeChild(elm); // 从该节点的父级节点中移除该节点
  parent.elm.appendChild(document.createTextNode("")); // 由于上一步移除了该节点，同时还会附带移除一个空文本节点，为了保持结构一致，添加回来这个空文本节点
  let resultSet = analysisInstructions(vm, instructions, elm, parent); // 分析指令
  return virtualNode;
}
function getVirtualNodeData(instructions) {
  // 解析指令中的数据,返回被切割后的指令数组
  let insSet = instructions.trim().split(" ");
  if (insSet.length !== 3 || (insSet[1] !== "in" && insSet[1] !== "of")) {
    throw new Error("error");
  }
  return insSet;
}
function analysisInstructions(vm, instructions, elm, parent) {
  let insSet = getVirtualNodeData(instructions); // 获得整个被切割后的指令数组
  let dataSet = getValue(vm._data, insSet[2]); // 在总数据中取得“(key) in list”中的list
  if (!dataSet) {
    // 如果在总数据中找不到就报错
    throw new Error("error");
  }
  let resultSet = [];
  for (let i = 0; i < dataSet.length; i++) {
    let tempDom = document.createElement(elm.nodeName); // for指令所在的元素的标签是什么就创建什么临时节点
    tempDom.innerHTML = elm.innerHTML; // 如果for指令所在的元素的标签里有innerHTML，则一并创建出来
    let env = analysisKV(insSet[0], dataSet[i], i); // env为每次循环后生成的新的元素的局部变量(<li v-for="(key, index) in list"></li>的每次生成的li元素的局部变量)
    tempDom.setAttribute("env", JSON.stringify(env)); // 将变量设置到DOM中
    parent.elm.appendChild(tempDom); // 给父级添加这个dom
    resultSet.push(tempDom);
  }
  return resultSet;
}
function analysisKV(instructions, value, index) {
  // instructions为(key, index)这样的东西
  if (/([a-zA-Z0-9_$]+)/.test(instructions)) {
    // 如果带括号就去括号
    instructions = instructions.trim();
    instructions = instructions.substring(1, instructions.length - 1);
  }
  let keys = instructions.split(",");
  if (keys.length === 0) {
    throw new Error("error");
  }
  let obj = {};
  if (keys.length >= 1) {
    // 只有key的情况
    obj[keys[0].trim()] = value;
  }
  if (keys.length >= 2) {
    // key,index的情况
    obj[keys[1].trim()] = index;
  }
  return obj;
}
